package com.wixc.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.CookieStore;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import com.google.gson.Gson;

/**
 * 登陆测试工具类，成功<br>
 * 密码验证使用js,<br>
 * 注意页面上几个动态参数
 */
public class LoginUtil extends EasyHttpClient {
	/**
	 * js文件缓存
	 */
	public static Map<String, String> jsCache = new ConcurrentHashMap<String, String>();

	private static Logger log = Logger.getLogger(LoginUtil.class);

	public static final String jquerypath = "/spider/jquery-2.1.4.js";

	/**
	 * 这个参数是为了传值，<br>
	 * 有时候某些需要的字段只能在登陆的时候获得，<br>
	 * 而这个字段在程序中非常有用，这时候需要放到这里<br>
	 */
	Map<String, Object> extra = new LinkedHashMap<String, Object>();

	/**
	 * 执行js的方法
	 * 
	 * @param js
	 *            js代码
	 * @param function
	 *            想要执行的js方法
	 * @param jsform
	 *            执行js的参数
	 * @return
	 * @throws Exception
	 */
	public static String getPassword(String js, String function, Object... jsform) throws Exception {

		// 非单例，每次都会new
		ScriptEngineManager manager = new ScriptEngineManager();
		// 获得js引擎
		ScriptEngine engine = manager.getEngineByName("js");
		// 将js代码注入引擎
		engine.eval(js);

		Invocable jsInvoke = (Invocable) engine;
		// 执行js方法
		Object result1 = jsInvoke.invokeFunction(function, jsform);
		// 返回结果
		return result1.toString();
	}

	/**
	 * 读取打包的js代码
	 * 
	 * @param filepath
	 * @return
	 */
	public static String readJs(String filepath) {
		String a = "";
		if (jsCache.get(filepath) != null) {
			log.info("readJs In cache : " + filepath);
			return jsCache.get(filepath);
		}
		;
		BufferedReader br = null;

		InputStream is = null;
		if (!filepath.startsWith("/")) {
			filepath = "/" + filepath;
		}
		String path = EasyHttpClient.class.getResource(filepath).toString();
		log.info("readJs In Path : " + path);
		try {
			is = EasyHttpClient.class.getResourceAsStream(filepath);

			StringBuilder strBlder = new StringBuilder("");
			br = new BufferedReader(new InputStreamReader(is, "utf-8"));
			String line = "";
			while (null != (line = br.readLine())) {
				strBlder.append(line + "\n");
			}
			a = strBlder.toString();
			br.close();
		} catch (FileNotFoundException e) {
			log.error(e.getMessage(), e);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			try {
				if (is != null) {
					is.close();
				}
				if (br != null) {
					br.close();
				}
			} catch (IOException e) {
				log.error(e.getMessage(), e);
			}
		}
		log.info("read " + filepath + " length:" + a.length());
		jsCache.put(filepath, a);
		return a;
	}

	/**
	 * 删除文件
	 * 
	 * @param jsfile
	 */
	public static void deleteFile(String jsfile) {
		FileUtils.deleteQuietly(new File(jsfile));
	}

	/**
	 * 读取打包的js代码
	 * 
	 * @param filepath
	 * @return
	 */
	public static byte[] readPhantomjs(String filepath) {
		if (jsCache.get(filepath) != null) {
			String a = jsCache.get(filepath);
			return a.getBytes();
		}
		;
		byte[] b = null;
		InputStream is = null;
		if (!filepath.startsWith("/")) {
			filepath = "/" + filepath;
		}
		String path = EasyHttpClient.class.getResource(filepath).toString();
		log.info("readJs In Path : " + path);
		try {
			is = EasyHttpClient.class.getResourceAsStream(filepath);
			b = IOUtils.toByteArray(is);

		} catch (FileNotFoundException e) {
			log.error(e.getMessage(), e);
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				log.error(e.getMessage(), e);
			}
		}
		jsCache.put(filepath, new String(b));
		return b;
	}

	/**
	 * 进行用户名密码校验
	 * 
	 * @param username
	 *            长度小于2，或者4位以下纯数字，pass
	 * @param password
	 *            长度小于等于4，或者6位以下纯数字，pass
	 * @return
	 */
	public static boolean checkUser(String username, String password) {
		if (null == username || username.trim().length() < 2 || username.trim().matches("\\d{0,4}")) {
			return false;
		}
		if (null == password || password.trim().length() <= 4 || password.trim().matches("\\d{4,5}")) {
			return false;
		}
		return true;
	}

	/**
	 * 获取加密参数
	 * 
	 * @param url
	 *            第一个访问的URL，一般为登陆页面
	 * @param times
	 *            获取参数失败重试次数
	 * @param css
	 *            获取参数使用的css，必须是 类似 doc.select("#id").attr("value");
	 * @return 返回顺序与传递进来的css参数顺序一致
	 */
	public String[] retry(String url, int times, String... css) {
		String html = Get(url);
		Document doc = Jsoup.parse(html);
		String a[] = new String[css.length];
		for (int i = 0; i < css.length; i++) {
			a[i] = doc.select(css[i]).attr("value");
		}

		boolean isNull = false;
		for (String string : a) {
			if (string == null || string.equals("")) {
				isNull = true;
				break;
			}
		}
		if (!isNull) {
			return a;
		}
		if (isNull && times > 0) {
			return retry(url, --times, css);
		}
		return null;
	}

	public static void main(String[] args) {
		System.out.println(checkUser("王的", "ssss11"));
	}

	/**
	 * @param codestr
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> json2Map(String json) {
		Gson gson = new Gson();
		Map<String, Object> map = null;
		try {
			map = gson.fromJson(json, Map.class);
		} catch (Exception e) {
			log.info("json----------------------->" + json);
			log.error("LoginUtil.json2Map()-------------->" + e.getMessage());
		}
		return map;
	}

	/**
	 * @param string
	 * @param imgsrc
	 * @return
	 */
	public static String tidyUrl(String referer, String url) {
		String nurl = "";
		try {
			if (!url.startsWith("http")) {
				URL u = new URL(referer);
				nurl = new URL(u, url).toString();
			} else {
				return url;
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		return nurl;
	}

	/**
	 * 这个参数是为了传值，<br>
	 * 有时候某些需要的字段只能在登陆的时候获得，<br>
	 * 而这个字段在程序中非常有用，这时候需要放到这里<br>
	 * 这个方法永远不会null
	 * 
	 * @return
	 */
	public Map<String, Object> getExtra() {
		if (extra == null) {
			extra = new LinkedHashMap<String, Object>();
		}
		return extra;
	}

	/**
	 * 这个参数是为了传值，<br>
	 * 有时候某些需要的字段只能在登陆的时候获得，<br>
	 * 而这个字段在程序中非常有用，这时候需要放到这里<br>
	 * 
	 * @param name
	 * @param value
	 */
	public void putExtra(String key, Object value) {
		getExtra().put(key, value);
	}

	/**
	 * 将cookiestore转换成string<br>
	 * 如果为空，使用默认对象
	 * 
	 * @param cookieStore
	 * @return
	 */
	public String CookieStore2String(CookieStore cookieStore) {
		if (cookieStore == null) {
			cookieStore = this.getCookieStore();
		}
		StringBuffer sb = new StringBuffer();
		for (Cookie cookie : cookieStore.getCookies()) {
			sb.append(cookie.getName() + "=" + cookie.getValue() + ";");
		}
		String cookie = sb.toString();
		cookie = cookie.substring(0, cookie.length() - 1);
		return cookie;
	}

	public void addCookie(String name, String value, String domain, Date expiry, String path) {
		BasicClientCookie cookie = new BasicClientCookie(name, value);
		if (domain != null && !domain.equals("")) {
			cookie.setDomain(domain);
		}
		if (expiry != null) {
			cookie.setExpiryDate(expiry);
		}
		if (path != null && !path.equals("")) {
			cookie.setPath(path);
		}

		this.getCookieStore().addCookie(cookie);
	}

}
